package com.jiepos.mpos.core.util;

import java.nio.ByteBuffer;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 * <p>标题: —— 3des加解密算法</p>
 * <p>描述: —— 简要描述类的职责、实现方式、使用注意事项等</p>
 * <p>模块: 通用平台</p>
 * @author 娄伟峰
 * @version 1.0

 */
public class Tool3DES {
    public static  final Logger log = LoggerFactory.getLogger(Tool3DES.class);

    static String DES = "DES/ECB/NoPadding";
    static String TriDes = "DESede/ECB/NoPadding";
 //   static String TriDes = "DESede/ECB/NoPadding";
  //  static String TriDes = "DESede/ECB/Zeros";
//    static String DES = "DES";
//    static String TriDes = "DESede";

    public static byte[] des_crypt(byte key[], byte data[]) {
        try {
            KeySpec ks = new DESKeySpec(key);
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DES");
            SecretKey ky = kf.generateSecret(ks);
            Cipher c = Cipher.getInstance(DES);
            c.init(Cipher.ENCRYPT_MODE, ky);
            return c.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] des_decrypt(byte key[], byte data[]) {
        try {
            KeySpec ks = new DESKeySpec(key);
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DES");
            SecretKey ky = kf.generateSecret(ks);

            Cipher c = Cipher.getInstance(DES);
            c.init(Cipher.DECRYPT_MODE, ky);
            return c.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 3des加密算法
     * @param key
     * @param data
     * @return
     */
    public static String trides_crypt(String strKey, String strData) {
    	strKey = strKey.toUpperCase();
    	strData = strData.toUpperCase();
       	byte key[] = hexToBytes(strKey);
    	byte data[] = hexToBytes(strData);
        try {
            byte[] k = new byte[24];

            int len = data.length;
            if (data.length % 8 != 0) {
                len = data.length - data.length % 8 + 8;
            }
            byte[] needData = null;
            if (len != 0)
                needData = new byte[len];

            for (int i = 0; i < len; i++) {
                needData[i] = 0x00;
            }

            System.arraycopy(data, 0, needData, 0, data.length);

            if (key.length == 16) {
                System.arraycopy(key, 0, k, 0, key.length);
                System.arraycopy(key, 0, k, 16, 8);
            } else {
                System.arraycopy(key, 0, k, 0, 24);
            } 
            Security.addProvider(new com.sun.crypto.provider.SunJCE()); 

            KeySpec ks = new DESedeKeySpec(k);
             SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");
            SecretKey ky = kf.generateSecret(ks); 
          /*  KeyGenerator kg = KeyGenerator.getInstance("DESede");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");  
		    secureRandom.setSeed("37d5aed075525d4fa0fe635231cba447".getBytes());  
    		kg.init(secureRandom);
    		SecretKey ky = kg.generateKey();*/
    		
    		

            Cipher c = Cipher.getInstance(TriDes);
            c.init(Cipher.ENCRYPT_MODE, ky);
            return byte2hex(c.doFinal(needData)).toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 3des加密算法
     * @param key
     * @param data
     * @return
     */
    public static byte[] tridesCryptByte(String privateKeyStr, String strData) {
    	Signature sign=null;
    	try {
	    	//实例化一个用SHA算法进行散列，用RSA算法进行加密的Signature.
	    	sign = Signature.getInstance("SHA1WithRSA");
		} catch (NoSuchAlgorithmException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
		}
		try {
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			//EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(toBytes(privateKeyStr));
			byte [] privKeyByte = Base64.decodeBase64(privateKeyStr);
			PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyByte);
			//  KeySpec privateKeySpec = new X509EncodedKeySpec(privateKeyStr.getBytes());
			RSAPrivateKey privateKey = (RSAPrivateKey)keyFactory.generatePrivate(privateKeySpec);    		 
    		//设置加密散列码用的私钥
    		sign.initSign(privateKey);
    		//设置散列算法的输入
    		sign.update(strData.getBytes());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		 
		byte data[]=null;
		try {
			//进行散列，对产生的散列码进行加密并返回
			data=sign.sign();
		} catch (SignatureException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return data;
     
    }
    
    private static byte[] toBytes(String str) {
        if(str == null) {
            throw new IllegalArgumentException("binary string is null");
        }
        char[] chs = str.toCharArray();
        byte[] bys = new byte[chs.length / 2];
        int offset = 0;
        int k = 0;
        while(k < chs.length) {
            bys[offset++] = (byte)((toInt(chs[k++]) << 4) | toInt(chs[k++]));
        }
        return bys;
    }
    private static int toInt(char a) {
        if(a >= '0' && a <= '9') {
            return a - '0';
        }
        if(a >= 'a' && a <= 'f') {
            return a - 'a' + 10;
        }
        if(a >= 'A' && a <= 'F') {
            return a - 'A' + 10;
        }
        throw new IllegalArgumentException("parameter \"" + a + "\"is not hex number!");
    }
    /**
     * 3des解密算法
     * @param key
     * @param data
     * @return
     */
    public static String trides_decrypt(String strKey, String strData) {
    	strKey = strKey.toUpperCase();
    	strData = strData.toUpperCase();
    	byte key[] = hexToBytes(strKey);
    	byte data[] = hexToBytes(strData);
        try {
            byte[] k = new byte[24];

            int len = data.length;
            if (data.length % 8 != 0) {
                len = data.length - data.length % 8 + 8;
            }
            byte[] needData = null;
            if (len != 0)
                needData = new byte[len];

            for (int i = 0; i < len; i++) {
                needData[i] = 0x00;
            }

            System.arraycopy(data, 0, needData, 0, data.length);

            if (key.length == 16) {
                System.arraycopy(key, 0, k, 0, key.length);
                System.arraycopy(key, 0, k, 16, 8);
            } else {
                System.arraycopy(key, 0, k, 0, 24);
            }
            KeySpec ks = new DESedeKeySpec(k);
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");
            SecretKey ky = kf.generateSecret(ks);

            Cipher c = Cipher.getInstance(TriDes);
            c.init(Cipher.DECRYPT_MODE, ky);
            return byte2hex(c.doFinal(needData)).toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) throws NoSuchAlgorithmException {      
    	
 

        //String key = "11111111111111110123456789ABCDEF";
    	String key = "0BC99CED1FA4C1CB9C47C2195BAC7CEA";
        String data = "de623e511345ff76e2c1b61fe239a905=f13e30d24b35d245f6cf6262648c43f8";
        System.out.println(trides_crypt(key,data));
        // data = new byte[8];
        // byte des_crypt[] = des_crypt(k1, data);
        // byte des_descrypt[] = des_decrypt(k2, des_crypt);
        // byte result[] = des_crypt(k1, des_descrypt);
 /*       System.out.println(trides_crypt("00aa1248f3e71c6eaed56138f6671bec","775a874e0c142802"));

     
        //775A874E0C142802原始数据
        //88A578B1F3EBD7FD补位数据
        //15517e395660511ad3eeeb5b8da82ab5正确加密数据
         
//      /  System.out.println(byte2hex(result)); 
  	  // System.out.println(trides_decrypt(key, data));
        String random = "775a874e0c142802";
        String random1= "ffffffffffffffff";
        byte b1[] = hexToBytes(random);
		byte b2[] = hexToBytes(random1);
		int temp = b1.length;		 
	 	String newRandom = "";
		for (int i = 0; i < temp; i++) {		
			int  b = b1[i]^b2[i];	 
			newRandom = newRandom + Integer.toString(getUnsignedIntt((byte)b), 0x10);
		} 
		   System.out.println(trides_crypt("00aa1248f3e71c6eaed56138f6671bec", newRandom));		
		   */
		   
		/*   String randomKey1 = Tool3DES.byte2hex("703E".getBytes());//.trides_crypt("00aa1248f3e71c6eaed56138f6671bec", "deda8a0d9af527d5");
		//	String randomKey2 = Tool3DES.getNewRandomByKey("00aa1248f3e71c6eaed56138f6671bec", "deda8a0d9af527d5");
			System.out.println(randomKey1);*/
	/*		
			
			byte b1[] = hexToBytes("06123456ffffffff");
			byte b2[] = hexToBytes("0000137000062014");
			int temp = b1.length;		 
			String newRandom = "";
			for (int i = 0; i < temp; i++) {		
				int b = b1[i]^b2[i];	 
				newRandom = newRandom + String.format("%02X", getUnsignedIntt((byte)b));
			} 
			System.out.println(newRandom);
			
			System.out.println(trides_decrypt("0123456789ABCDEF0123456789ABCDEF","3EC61577D1ACD86CCA3F885CB98B8BDF"));*/
        //System.out.println(encodeStrTo16((stringToAscii("00"))));
      /*  try {
			String s = "00";
			byte[] b = s.getBytes();
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < b.length; i++) {
				sb.append(Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1));
			}
			System.out.println(sb);
		} catch (Throwable e) {
			e.printStackTrace();
		}*/
    }
    /**
     * 字符串转16进制ascii
     * @param s
     * @return
     */
    public static String stringTo16Ascii(String s){
    	StringBuffer sb = new StringBuffer();
    	try {
			 
			byte[] b = s.getBytes();
			for (int i = 0; i < b.length; i++) {
				sb.append(Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1));
			}
		
		} catch (Throwable e) {
			e.printStackTrace();
		}
		 return sb.toString();
    }
    /* 
    * 16进制数字字符集 
    */ 
    private static String hexString="0123456789ABCDEF"; 
    public static String encodeStrTo16(String str) { 
	    //根据默认编码获取字节数组 
	    byte[] bytes=str.getBytes(); 
	    StringBuilder sb=new StringBuilder(bytes.length*2); 
	    //将字节数组中每个字节拆解成2位16进制整数 
	    for(int i=0;i<bytes.length;i++) 
	    { 
	    sb.append(hexString.charAt((bytes[i]&0xf0)>>4)); 
	    sb.append(hexString.charAt((bytes[i]&0x0f)>>0)); 
	    } 
	    return sb.toString(); 
    } 
    /**
     * 获取密码和卡号异或结果
     * @param pin
     * @param pan
     * @return
     */
    public static String getXorPinCardData(String pin,String pan){

		byte b1[] = hexToBytes(pin);
		byte b2[] = hexToBytes(pan);
		int temp = b1.length;		 
		String newRandom = "";
		for (int i = 0; i < temp; i++) {		
			int b = b1[i]^b2[i];	 
			newRandom = newRandom + String.format("%02X", getUnsignedIntt((byte)b));
		} 
		return newRandom;
    }
    
    
    /**
     * 获取异或随机数
     * @param key 加密秘钥
     * @param random 随机数
     */
    public static String getNewRandomByKey(String key,String random){
		String random1= "ffffffffffffffff";
		byte b1[] = hexToBytes(random);
		byte b2[] = hexToBytes(random1);
		int temp = b1.length;		 
		String newRandom = "";
		for (int i = 0; i < temp; i++) {		
			int b = b1[i]^b2[i];	 
			newRandom = newRandom + String.format("%02X", getUnsignedIntt((byte)b));
		} 
	   return trides_crypt(key, newRandom);		

    }
    
    /**
     * 将data数据转换为int类型
     * @param data
     * @return
     */
    public static int getUnsignedIntt(byte  data){    
        return (int)data&0xFF;
     }

 
    /**
     * 字节数组转换成字符串
     * @param data
     * @return
     */
    public static String byte2hex(byte[] data) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            String temp = Integer.toHexString(((int) data[i]) & 0xFF);
            for (int t = temp.length(); t < 2; t++) {
                sb.append("0");
            }
            sb.append(temp);
        }
        return sb.toString();
    }

    /**
     * 将字符串转换成字节数组
     * @param str
     * @return
     */
    public static byte[] hexToBytes(String str) {
        if (str == null) {
            return null;
        } else if (str.length() < 2) {
            return null;
        } else {
            int len = (str.length() / 2 );
            byte[] buffer = new byte[len];
            for (int i = 0; i < len; i++) {
                buffer[i] = (byte) Integer.parseInt(
                        str.substring(i * 2, i * 2 + 2), 16);
    
            }
            return buffer;
        }
    }
    /**
     * 获取16进制数据
     * @param msg
     * @return
     */
    public static String get16String(byte[] msg){
    	String returnMsg = "";
    	for(int i = 0 ; i <msg.length; i++){
    	//	returnMsg = returnMsg + Integer.toString(getUnsignedIntt((byte)msg[i]), 0x10);
    		/*String mm = Integer.toString(getUnsignedIntt((byte)msg[i]), 0x10);
    		System.out.println("mm=="+getUnsignedIntt((byte)msg[i]));*/
    		returnMsg = returnMsg + String.format("%02X",getUnsignedIntt((byte)msg[i]));
//    	/	System.out.println("returnMsg=="+returnMsg);
		}
    	return returnMsg;
    }
    
    /**
     * 获取16进制数据
     * @param msg
     * @return
     */
    public static String get16String(byte[] msg,int offset, int length){
    	String returnMsg = "";
    	for(int i = offset ; i <offset+length; i++){
    	//	log.debug("buf["+i+"]==="+msg[i]);
    	//	returnMsg = returnMsg + Integer.toString(getUnsignedIntt((byte)msg[i]), 0x10);
    		/*String mm = Integer.toString(getUnsignedIntt((byte)msg[i]), 0x10);
    		System.out.println("mm=="+getUnsignedIntt((byte)msg[i]));*/
    		returnMsg = returnMsg + String.format("%02X",getUnsignedIntt((byte)msg[i]));
//    	/	System.out.println("returnMsg=="+returnMsg);
    		
		}
    	log.debug("returnMsg==="+returnMsg);
    	return returnMsg;
    }
    /**
     * 将字符串前几位拼装成长度，一般是4位
     * @param byteLength
     * @param intValue
     * @return
     */
	public static byte[] intToByteArray(int byteLength, int intValue) {
	    return ByteBuffer.allocate(byteLength).putInt(intValue).array();
	}
	/**
	 * 拼装字节长度数组和字符串字节数组为一个字节数组
	 * @param array1
	 * @param array2
	 * @return
	 */
	public static byte[] combineByteArray(byte[] array1, byte[] array2) {
	    byte[] combined = new byte[array1.length + array2.length];
	    System.arraycopy(array1, 0, combined, 0, array1.length);
	    System.arraycopy(array2, 0, combined, array1.length, array2.length);
	    return combined;
	}
	
	   /** 
     * BCD码转为10进制串(阿拉伯数据) 
     * @param: BCD码 
     * @return: 10进制串 
     */  
    public static String bcd2Str(byte[] bytes) {  
        StringBuffer temp = new StringBuffer(bytes.length * 2);  
        for (int i = 0; i < bytes.length; i++) {  
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));  
            temp.append((byte) (bytes[i] & 0x0f));  
        }  
        return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp  
                .toString().substring(1) : temp.toString();  
    }  
    
    
    /** 
     * 10进制串转为BCD码 
     * @param: 10进制串 
     * @return: BCD码 
     */  
    public static byte[] str2Bcd(String asc) {  
        int len = asc.length();  
        int mod = len % 2;  
        if (mod != 0) {  
            asc = "0" + asc;  
            len = asc.length();  
        }  
        byte abt[] = new byte[len];  
        if (len >= 2) {  
            len = len / 2;  
        }  
        byte bbt[] = new byte[len];  
        abt = asc.getBytes();  
        int j, k;  
        for (int p = 0; p < asc.length() / 2; p++) {  
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {  
                j = abt[2 * p] - '0';  
            } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {  
                j = abt[2 * p] - 'a' + 0x0a;  
            } else {  
                j = abt[2 * p] - 'A' + 0x0a;  
            }  
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {  
                k = abt[2 * p + 1] - '0';  
            } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {  
                k = abt[2 * p + 1] - 'a' + 0x0a;  
            } else {  
                k = abt[2 * p + 1] - 'A' + 0x0a;  
            }  
            int a = (j << 4) + k;  
            byte b = (byte) a;  
            bbt[p] = b;  
        }  
        return bbt;  
    }  
    
    /**
     * 将16进制字节码转换成字符串
     * @param s 需要处理的字符串
     * @param len 需要去除的长度
     * @return
     */
	 public static String toStringHex(String s,int len) {
		int tempLen = (s.length() / 2)-len;
		byte[] baKeyword = new byte[tempLen];
		for (int i = 0; i < baKeyword.length; i++) {
			try {
				String str = s.substring(i * 2, i * 2 + 2);
				 
				baKeyword[i] = (byte) (0xff & Integer.parseInt(str, 16));
			 
			
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			s = new String(baKeyword, "utf-8");// UTF-16le:Not
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return s;
	} 
 
}